//! Benchmark comparing Zig vs Rust syscall performance
//! SPDX-License-Identifier: MPL-2.0

const std = @import("std");
const lib = @import("../src/lib.zig");
const Context = @import("../src/context.zig").Context;

// Mock context for benchmarking
const BenchContext = struct {
    const Self = @This();
    
    pub fn user_space(self: *Self) BenchUserSpace {
        _ = self;
        return BenchUserSpace{};
    }
    
    pub fn current_process(self: *Self) BenchProcess {
        _ = self;
        return BenchProcess{};
    }
    
    pub fn current_thread(self: *Self) BenchThread {
        _ = self;
        return BenchThread{};
    }
};

const BenchUserSpace = struct {
    pub fn read_bytes(self: @This(), addr: u64, buf: []u8) !usize {
        _ = self;
        _ = addr;
        _ = buf;
        return 0;
    }
    
    pub fn write_bytes(self: @This(), addr: u64, data: []const u8) !usize {
        _ = self;
        _ = addr;
        _ = data;
        return data.len;
    }
};

const BenchProcess = struct {
    pub fn pid(self: @This()) u32 {
        _ = self;
        return 1;
    }
};

const BenchThread = struct {
    pub fn tid(self: @This()) u32 {
        _ = self;
        return 1;
    }
};

/// Benchmark syscall dispatch overhead
fn benchmark_syscall_dispatch(iterations: u32) !u64 {
    var bench_ctx = BenchContext{};
    var ctx = Context.from_mock(&bench_ctx);
    
    const start_time = std.time.nanoTimestamp();
    
    var i: u32 = 0;
    while (i < iterations) : (i += 1) {
        // Benchmark getpid syscall (fast syscall)
        _ = lib.handle_syscall(39, 0, 0, 0, 0, 0, 0, &ctx);
    }
    
    const end_time = std.time.nanoTimestamp();
    return @intCast(end_time - start_time);
}

/// Benchmark error handling overhead
fn benchmark_error_handling(iterations: u32) !u64 {
    var bench_ctx = BenchContext{};
    var ctx = Context.from_mock(&bench_ctx);
    
    const start_time = std.time.nanoTimestamp();
    
    var i: u32 = 0;
    while (i < iterations) : (i += 1) {
        // Benchmark invalid syscall (error path)
        _ = lib.handle_syscall(999999, 0, 0, 0, 0, 0, 0, &ctx);
    }
    
    const end_time = std.time.nanoTimestamp();
    return @intCast(end_time - start_time);
}

/// Benchmark statistics collection overhead
fn benchmark_stats_collection(iterations: u32) !u64 {
    lib.reset_stats();
    
    var bench_ctx = BenchContext{};
    var ctx = Context.from_mock(&bench_ctx);
    
    const start_time = std.time.nanoTimestamp();
    
    var i: u32 = 0;
    while (i < iterations) : (i += 1) {
        _ = lib.handle_syscall(39, 0, 0, 0, 0, 0, 0, &ctx);
        _ = lib.get_stats(); // Get stats each time
    }
    
    const end_time = std.time.nanoTimestamp();
    return @intCast(end_time - start_time);
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    
    try stdout.print("Zig Syscall Performance Benchmark\n");
    try stdout.print("==================================\n\n");
    
    const iterations = 1000000;
    
    // Benchmark syscall dispatch
    const dispatch_time = try benchmark_syscall_dispatch(iterations);
    const dispatch_ns_per_call = dispatch_time / iterations;
    try stdout.print("Syscall dispatch: {} ns total, {} ns per call\n", 
                     .{ dispatch_time, dispatch_ns_per_call });
    
    // Benchmark error handling
    const error_time = try benchmark_error_handling(iterations);
    const error_ns_per_call = error_time / iterations;
    try stdout.print("Error handling: {} ns total, {} ns per call\n", 
                     .{ error_time, error_ns_per_call });
    
    // Benchmark stats collection
    const stats_time = try benchmark_stats_collection(iterations);
    const stats_ns_per_call = stats_time / iterations;
    try stdout.print("Stats collection: {} ns total, {} ns per call\n", 
                     .{ stats_time, stats_ns_per_call });
    
    // Show final statistics
    const final_stats = lib.get_stats();
    try stdout.print("\nFinal Statistics:\n");
    try stdout.print("Total calls: {}\n", .{final_stats.total_calls});
    try stdout.print("Error calls: {}\n", .{final_stats.error_calls});
    try stdout.print("Success rate: {d:.2}%\n", 
                     .{@as(f64, @floatFromInt(final_stats.total_calls - final_stats.error_calls)) / 
                       @as(f64, @floatFromInt(final_stats.total_calls)) * 100.0});
}